说明
本文适合跨账户迁移虚机。
原理通过公开的sas url 复制磁盘镜像到存储账户里,然后再从存储账户的vhd文件创建托管磁盘,再利用托管磁盘创建虚机
需要注意的是:虚机加载的额外磁盘需要卸掉,或者在fstab 磁盘加载项添加 nofail, 如 centos配置:
UUID=1037feaf-5034-446c-bbdc-e1958be6b35a /data xfs defaults,nofail,nodev,nouser,noexec,nosuid,noatime,nodiratime 0 0
如果没修改,可以在已启动的虚机里加载 vhd文件 或 托管磁盘,修改fstab后在创建虚机
参考:
https://docs.microsoft.com/zh-cn/cli/azure/reference-index?view=azure-cli-latest
Azure 登陆
## 切换到中国云
az cloud set -n AzureChinaCloud
## 登陆
az login
## 浏览器打开,先用账户登陆Azure portal,然后在新tab page里打开
## https://microsoft.com/deviceloginchina
## 如果需要设置订阅
az account set --subscription $s_SubscriptionId
用到的变量
## t_ 表示target_, 代表目标资源
## s_ 表示source_, 代表源资源
##--源资源变量------------------------------------------------------
## 源订阅
s_SubscriptionId=ddrt394e-0463-4eta5-8d04-c94wetfd879dc
## 源区域
s_Location="chinaeast"
## 源资源组
s_ResourceGroupName="server_rg"
## 源托管磁盘镜像名
s_SnapshotName="server01_OsDisk-hdd201801"
##--目标资源变量------------------------------------------------------
## 目标订阅
t_SubscriptionId=653gfb1f7-f219-4sgfeb-eret-31wrtwe1efb0
## 目标区域, chinanorth chinaeast
t_Location="chinaeast"
## 目标资源组
t_ResourceGroupName="test_rg"
##--目标存储账户变量------------------------------------------------------
## 目标存储账户名
t_StorageAccountName="serverstg01"
## 目标存储账户容器名
t_StorageContainerName="data"
## 存储账户访问密匙,这里随便几个字符表示一下
t_StorageAccountKey="aA8bfS4CnG0t7tW+QudkMYYt+IBbp6ha7iPzo9mNFDGp7M4u2UBw=="
##--目标网络资源变量------------------------------------------------------
## 高可用集名
t_HASetName="HASet"
## 安全组名
t_NSGName="test_ng"
## 公网IP
t_PIPName1="test01_IP1"
t_PIPName2="test02_IP1"
## 虚拟网卡名
t_NICName1="test01_nic1"
t_NICName2="test02_nic1"
## 虚拟网络名
t_VnetName="test01-vnet-101e"
## 虚拟网络地址空间
t_VnetAddressPrefix="10.10.10.0/24 10.10.11.0/24 10.10.12.0/24"
## 子网1名
t_SubnetName1="test01-snet-101e"
## 子网1地址
t_SubnetNamePrefix1="10.10.10.0/24"
## 子网2名和子网2地址
t_SubnetName2="test_app_gatewy"
t_SubnetNamePrefix2="10.10.11.0/24"
##--新建资源变量------------------------------------------------------
## 导出时间限制,过期时间,3600 秒 = 1 小时
## 创建的sas url 连接时,设置能够访问的时间,就是说从创建开始到不能从这个sas url下载磁盘镜像的时间长度
sasExpiryDuration=3600
## 目标 VHD 文件保存名
t_VHDFileName="osdisk.vhd"
##--新建托管磁盘变量------------------------------------------------------
## 新建的托管磁盘名
t_ManagedDiskName="test01_OsDisk_1"
## 新建虚机存放格式,这里用ssd, Premium_LRS or Standard_LRS
t_Sku="Premium_LRS"
## 新建磁盘大小,单位GB
t_DiskSize=32
##--新建虚机变量------------------------------------------------------
## 新建虚机名
t_VMName1="test01"
## 新建虚机类型
t_OS_Type=linux
## 新建虚机大小
t_Size="Standard_DS2_v2"
创建资源组
## 查询资源组里的资源,不带--resource-group查询订阅的所有资源
az resource list --resource-group $t_ResourceGroupName --output table
## 创建资源组
az group create \
--name $t_ResourceGroupName \
--location $t_Location
创建安全组
az network nsg create \
--location $t_Location \
--resource-group $t_ResourceGroupName \
--name $t_NSGName
开启端口3890
az network nsg rule create \
--location $t_Location \
--resource-group $t_ResourceGroupName \
--nsg-name $t_NSGName \
--name RDP \
--protocol tcp \
--direction inbound \
--source-address-prefix '*' \
--source-port-range '*' \
--destination-address-prefix '*' \
--destination-port-range 3890 \
--access allow \
--priority 1100
开启端口22
az network nsg rule create \
--location $t_Location \
--resource-group $t_ResourceGroupName \
--nsg-name $t_NSGName \
--name SSH \
--protocol tcp \
--direction inbound \
--source-address-prefix '*' \
--source-port-range '*' \
--destination-address-prefix '*' \
--destination-port-range 22 \
--access allow \
--priority 1100
开启80端口
az network nsg rule create \
--location $t_Location \
--resource-group $t_ResourceGroupName \
--nsg-name $t_NSGName \
--name HTTP \
--protocol tcp \
--direction inbound \
--source-address-prefix '*' \
--source-port-range '*' \
--destination-address-prefix '*' \
--destination-port-range 80 \
--access allow \
--priority 1200
创建可用集
az vm availability-set create \
--name $t_HASetName \
--resource-group $t_ResourceGroupName \
--platform-fault-domain-count 2 \
--platform-update-domain-count 5
创建虚拟网络和子网
az network vnet create \
--resource-group $t_ResourceGroupName \
--name $t_VnetName \
--address-prefix $t_VnetAddressPrefix \
--subnet-name $t_SubnetName1 \
--subnet-prefix $t_SubnetNamePrefix1
## 其它参数:DDOS防护,启用的是标准防护,需要收费,默认基础防护不需要设置。
[--ddos-protection {false, true}]
[--ddos-protection-plan]
[--vm-protection {false, true}]
创建子网
az network vnet subnet create \
--resource-group $t_ResourceGroupName \
--vnet-name $t_VnetName \
--name t_SubnetName2 \
--address-prefix t_SubnetNamePrefix2 \
--network-security-group $t_NSGName
## 其它参数:
--route-table MyRouteTable
[--service-endpoints]
创建存储帐户
az storage account create \
--resource-group $t_ResourceGroupName \
--location $t_Location \
--name $t_StorageAccountName \
--kind Storage \
--sku Standard_LRS
创建存储容器
az storage container create \
--account-name $t_StorageAccountName \
--name $t_StorageContainerName
查询存储第一个access key
storageAccountKey=$(az storage account keys list \
--account-name $t_StorageAccountName \
--resource-group $t_ResourceGroupName \
--query [0].value --output tsv)
托管磁盘转vhd
## 登陆到源订阅上操作
## 从托管磁盘镜像创建sas url,通过此连接可用于外网用户直接访问下载镜像
## 也可以直接从portal界面创建
s_SAS=$(az snapshot grant-access --resource-group $s_ResourceGroupName --name $s_SnapshotName --duration-in-seconds $sasExpiryDuration --query [accessSas] -o tsv)
## 此连接将会是这样一个url
## echo $s_SAS
## https://md-jzj4xh1pwpkc.blob.core.chinacloudapi.cn/d1dcd5z4mb2g/abcd?sv=2017-04-17&sr=b&si=4484c9bb-e110-424c-aae8-169cca49c4af&sig=ARBeP4FNuhlphRB03a97c71HXQ9P8Xd1IRu9Eb0x8zU%3D
## 登陆到目标订阅上操作
## 将sar url 复制下来,并复制给变量
s_SAS="https://md-jzj4xh1pwpkc.blob.core.chinacloudapi.cn/d1dcd5z4mb2g/abcd?sv=2017-04-17&sr=b&si=4484c9bb-e110-424c-aae8-169cca49c4af&sig=ARBeP4FNuhlphRB03a97c71HXQ9P8Xd1IRu9Eb0x8zU%3D"
## 通过异步复制,将$s_SAS 的磁盘镜像复制到存储账户里,存为一个vhd文件
az account set --subscription $t_SubscriptionId
az storage blob copy start \
--destination-blob $t_VHDFileName \
--destination-container $t_StorageContainerName \
--account-name $t_StorageAccountName \
--account-key $t_StorageAccountKey \
--source-uri $s_SAS
vhd转托管磁盘
## 存储帐户中从 VHD 文件创建托管磁盘,如果未设置大小,默认和源镜像一样大
az account set --subscription $t_SubscriptionId
## 获取存储账户密匙
storageAccountKey=$(az storage account keys list \
--account-name $t_StorageAccountName \
--resource-group $t_ResourceGroupName \
--query [0].value --output tsv)
## 获取blob url
vhd_url=$(az storage blob url \
--name $t_VHDFileName \
--account-key $storageAccountKey \
--account-name $t_StorageAccountName \
--container-name $t_StorageContainerName)
## 查看vhd_url内容
## echo $vhd_url
## https://testserverdiag01.blob.core.chinacloudapi.cn/data/vm_os.vhd
az disk create \
--resource-group $t_ResourceGroupName \
--name $t_ManagedDiskName \
--location $t_Location \
--sku $t_Sku \
--size-gb $t_DiskSize \
--source $vhd_url
从托管磁盘镜像创建托管磁盘
az account set --subscription $t_SubscriptionId
## 获取托管磁盘镜像ID
snapshotId=$(az snapshot show --name $s_SnapshotName --resource-group $s_ResourceGroupName --query [id] -o tsv)
#通过镜像ID创建托管磁盘,如果未设置大小,默认和源镜像一样大
az disk create \
--resource-group $t_ResourceGroupName \
--name $t_ManagedDiskName \
--sku $t_Sku \
--size-gb $t_DiskSize \
--source $snapshotId
使用现有托管 OS 磁盘创建虚拟机
创建对外IP
az network public-ip create \
--name $t_PIPName1 \
--resource-group $t_ResourceGroupName \
--location $t_Location \
--allocation-method Static
## 其它参数:
[--dns-name] :--dns-name Mydnsname
[--idle-timeout]
[--ip-tags]
[--reverse-fqdn]
[--sku {Basic, Standard}]
[--tags]
[--version {IPv4, IPv6}]
[--zone {1, 2, 3}] : --zone 2
创建网卡(虚拟 NIC)
az network nic create \
--name $t_NICName1 \
--location $t_Location \
--resource-group $t_ResourceGroupName \
--vnet-name $t_VnetName \
--subnet $t_SubnetName \
--network-security-group $t_NSGName \
--public-ip-address $t_PIPName1
## 如果虚拟网络不再同一个资源组里,必须指定子网id,而不是子网名和虚拟网络名
## --subnet "/subscriptions/91913983-c6cc-4aea-a712-87dd97b5c85b/resourceGroups/tada-web-rg01e/providers/Microsoft.Network/virtualNetworks/tada-web-vnet-101e/subnets/tada-web-snet-102e"
获取托管磁盘ID
managedDiskId=$(az disk show --name $t_ManagedDiskName --resource-group $t_ResourceGroupName --query [id] -o tsv)
从托管磁盘中创建vm
az vm create --name $t_VMName1 \
--resource-group $t_ResourceGroupName \
--nics $t_NICName1 \
--attach-os-disk $managedDiskId \
--os-type $t_OS_Type \
--size $t_Size \
--availability-set $t_HASetName \
--os-disk-caching ReadOnly
## 多块网卡只需空格隔开,如:--nics $t_NICName11 $t_NICName11
上传本地vhd创建虚机
## 获取存储账户密匙
storageAccountKey=$(az storage account keys list \
--account-name $t_StorageAccountName \
--resource-group $t_ResourceGroupName \
--query [0].value --output tsv)
az storage blob upload
--account-name $t_StorageAccountName \
--container-name $t_StorageContainerName \
--account-key $storageAccountKey \
--type page \
--file /path/to/disk/mydisk.vhd \
--name $t_VHDFileName
az disk create \
--resource-group $t_ResourceGroupName \
--name $t_ManagedDiskName \
--sku $t_Sku \
--size-gb $t_DiskSize \
--source https://mystorageaccount.blob.core.chinacloudapi.cn/mydisks/myDisk.vhd
从自定义映像创建虚机
## 用vhd或托管磁盘创建虚机映像
az image create --os-type Windows -g $t_ResourceGroupName -n image1 --source myManagedDisk
az image create --os-type Windows -g $t_ResourceGroupName -n image1 --source https://mystorageaccount.blob.core.chinacloudapi.cn/mydisks/myDisk.vhd
az image list --resource-group $t_ResourceGroupName
az image show --name
--resource-group
[--expand]
## 查看可用虚机大小
az vm list-sizes --location $t_Location --output table
az vm list-skus --location $t_Location --output table
## 查看IP地址
az vm list-ip-addresses [--name] --resource-group $t_ResourceGroupName --output table
## 查看自定义虚机映像
az image list --resource-group $t_ResourceGroupName
az vm create \
--name $t_VMName1 \
--resource-group $t_ResourceGroupName \
--location $t_Location \
--image mycustomimage \
--vnet-name $t_VnetName \
--subnet $t_SubnetName1 \
--nics t_NICName1\
--availability-set $t_HASetName \
--os-type windows \
--os-disk-caching ReadOnly \
--storage-sku Premium_LRS \
--size Standard_DS2_v2 \
--os-disk-name $t_VMName1"_os" \
--private-ip-address 10.10.0.4/24 \
## 利用模板创建
https://github.com/Azure/azure-quickstart-templates/tree/master/201-vm-specialized-vhd
托管磁盘复制
## 最好先停止虚机或卸载托管磁盘,否则,如果磁盘正在写入数据,无法保证数据一致性,导致某些文件破坏或程序用不了。
## 获取托管磁盘ID
managedDiskId=$(az disk show --name $t_ManagedDiskName --resource-group $s_ResourceGroupName --query [id] -o tsv)
## 使用托管磁盘ID复制托管磁盘到不同的订阅或组
az account set --subscription $t_SubscriptionId
az disk create --resource-group $t_ResourceGroupName --name $t_ManagedDiskName --source $managedDiskId
托管磁盘直接导出
## 参考:https://docs.azure.cn/zh-cn/articles/azure-operations-guide/virtual-machines/aog-virtual-machines-howto-export-managed-disks
## 创建导出http url连接,相当于图像界面的export导出磁盘连接
## 如果是镜像,只需把az disk 换成 az snapshot
sas=$(az disk grant-access \
--duration-in-seconds 3600 \
--name $t_ManagedDiskName \
--resource-group $s_ResourceGroupName \
--query [accessSas] -o tsv)
## 复制
az storage blob copy start \
--destination-blob $t_VHDFileName \
--destination-container $t_StorageContainerName \
--account-name $t_StorageAccountName \
--account-key $storageAccountKey \
--source-uri $sas
导出blob
## 可以外网直接下载访问
存储参考:
https://azurecitadel.github.io/guides/cli/cli-4-bash/
blob=azuredeploy.json
container=templates
expiry=$(date '+%Y-%m-%dT%H:%MZ' --date "+30 minutes")
export accountName=$(az storage account list --resource-group ExampleResourceGroup --query [0].name --output tsv)
storageAccountKey=$(az storage account keys list --account-name $accountName --resource-group ExampleResourceGroup --query [0].value --output tsv)
sasToken=$(az storage blob generate-sas --account-name $accountName --account-key $storageAccountKey --container-name templates --name azuredeploy.json --permissions r --expiry $expiry --output tsv)
shortURL=$(az storage blob url --container-name $container --name $blob)
fullURL=$shortURL?$sasToken
echo $fullURL